/*
 *  banana project
 *  voice control iFly Auto transform
 *  public topic :
 *  @author		haosen
 *  @date		2019/09/16
 */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <iconv.h>
#include "qisr.h"
#include "msp_cmn.h"
#include "msp_errors.h"
#include "speech_recognizer.h"

#include <ros/ros.h>
#include "std_msgs/String.h"

#define FREAM_LEN 640
#define BUFFER_SIZE 4096

int flag = 0;
int flag_ok = 0;
int flag_no = 0;

static int upload_userwords()
{
  char* userwords = NULL;
  size_t len = 0;
  size_t read_len = 0;
  FILE* fp = NULL;
  int ret = -1;

  fp = fopen("/home/haosen/catkin_ws/src/voice/config/userwords.txt","rb");
  if(fp == NULL)
  {
    std::cout<<"\nopen[userwords.txt]failed "<<std::endl;
    goto upload_exit;
  }
  fseek(fp,0,SEEK_END);
  len = ftell(fp);
  fseek(fp,0,SEEK_SET);

  userwords = (char*)malloc(len+1);
  if(NULL == userwords)
  {
    std::cout<<"\n out of memory! \n"<<std::endl;
    goto upload_exit;
  }
  read_len = fread((void*)userwords, 1, len, fp);
  if (read_len != len)
  {
    std::cout<<"\nread [userwords.txt] failed!\n";
    goto upload_exit;
  }
  userwords[len] = '\0';

  MSPUploadData("userwords", userwords, len, "sub = uup, dtt = userword", &ret);
  if (MSP_SUCCESS != ret)
  {
    std::cout<<"\nMSPUploadData failed ! errorCode: %d \n", ret;
    goto upload_exit;
  }

upload_exit:
  if (NULL != fp)
  {
    fclose(fp);
    fp = NULL;
  }
  if (NULL != userwords)
  {
    free(userwords);
    userwords = NULL;
  }

  return ret;
}
static char *g_result = NULL;
static unsigned int g_buffersize = BUFFER_SIZE;

void on_result(const char *result, char is_last)
{
  if (result) {
    size_t left = g_buffersize - 1 - strlen(g_result);
    size_t size = strlen(result);
    if (left < size) {
      g_result = (char*)realloc(g_result, g_buffersize + BUFFER_SIZE);
      if (g_result)
        g_buffersize += BUFFER_SIZE;
      else {
        printf("mem alloc failed\n");
        return;
      }
    }
    strncat(g_result, result, size);
    //show_result(g_result, is_last);
  }
}
void on_speech_begin()
{
  if (g_result)
  {
    free(g_result);
  }
  g_result = (char*)malloc(BUFFER_SIZE);
  g_buffersize = BUFFER_SIZE;
  memset(g_result, 0, g_buffersize);

  std::cout<<"Start Listening...\n";
}
void on_speech_end(int reason)
{
  if (reason == END_REASON_VAD_DETECT)
    std::cout<<"\nSpeaking done \n";
  else
    std::cout<<"\nRecognizer error %d\n", reason;
}

static void microphone(const char* session_begin_params)
{
  int errcode;
  int i = 0;

  struct speech_rec iat;

  struct speech_rec_notifier recnotifier = {
    on_result,
        on_speech_begin,
        on_speech_end
  };

  errcode = sr_init(&iat, session_begin_params, SR_MIC, &recnotifier);
  if (errcode) {
    printf("speech recognizer init failed\n");
    return;
  }
  errcode = sr_start_listening(&iat);
  if (errcode) {
    printf("start listen failed %d\n", errcode);
  }
  /* demo 15 seconds recording */
  while(i++ < 15)
    sleep(1);
  errcode = sr_stop_listening(&iat);
  if (errcode) {
    printf("stop listening failed %d\n", errcode);
  }

  sr_uninit(&iat);
}

int main(int argc, char **argv)
{
  int ret = MSP_SUCCESS;
  const char* login_params = "appid = 5d7f299e, work_dir = .";

  /*
  * See "iFlytek MSC Reference Manual"
  */
  const char* session_begin_params =
      "sub = iat, domain = iat, language = zh_cn, "
      "accent = mandarin, sample_rate = 16000, "
      "result_type = plain, result_encoding = utf8";

  /* Login first. the 1st arg is username, the 2nd arg is password
   * just set them as NULL. the 3rd arg is login paramertes
   * */
  ret = MSPLogin(NULL, NULL, login_params);
  if (MSP_SUCCESS != ret)	{
    printf("MSPLogin failed , Error code %d.\n",ret);
    goto exit; // login fail, exit the program
  }
  printf("Uploading the user words ...\n");
  ret = upload_userwords();
  if (MSP_SUCCESS != ret)
    goto exit;
  std::cout<<"Uploaded successfully\n"<<std::endl;
  std::cout<<"Demo recognizing the speech from microphone\n"<<std::endl;
  std::cout<<"Speak in 15 seconds\n"<<std::endl;

  microphone(session_begin_params);

  std::cout<<"15 sec passed\n"<<std::endl;
exit:
  MSPLogout();


  //ros pubMsg
  ros::init(argc, argv, "pubtopic");
  ros::NodeHandle nh;
  ros::Publisher chatter_pub = nh.advertise<std_msgs::String>("banana_voice_control", 1000);

  std::cout<<"Send Cmd :"<< g_result <<std::endl;
  printf("send %s",g_result);
  std_msgs::String msg;
  msg.data = g_result;
  chatter_pub.publish(msg);


  return 0;
}
